﻿using System;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKArchMethodLibrary.Utils;

namespace YJKRamp.RampDataManager
{
	public class SegmentData
	{
		public XYZ StartPoint
		{
			get
			{
				return this.m_ptStart;
			}
			set
			{
				this.m_ptStart = value;
			}
		}

		public XYZ EndPoint
		{
			get
			{
				return this.m_ptEnd;
			}
			set
			{
				this.m_ptEnd = value;
			}
		}

		public double Bulge
		{
			get
			{
				return this.m_dBulge;
			}
			set
			{
				this.m_dBulge = value;
			}
		}

		public bool IsArc
		{
			get
			{
				return !Geometry.IsEqual(this.m_dBulge, 0.0);
			}
		}

		public double StartElevation
		{
			get
			{
				return this.m_dStartElevation;
			}
			set
			{
				this.m_dStartElevation = value;
			}
		}

		public double EndElevation
		{
			get
			{
				return this.m_dEndElevation;
			}
			set
			{
				this.m_dEndElevation = value;
			}
		}

		public double LeftWidth
		{
			get
			{
				return this.m_dLeftWidth;
			}
			set
			{
				this.m_dLeftWidth = value;
			}
		}

		public double RightWidth
		{
			get
			{
				return this.m_dRightWidth;
			}
			set
			{
				this.m_dRightWidth = value;
			}
		}

		public double VertArcRadius
		{
			get
			{
				return this.m_dVertArcRadius;
			}
			set
			{
				this.m_dVertArcRadius = value;
			}
		}

		public SegmentData(SegmentData rhs)
		{
			this.m_ptStart = rhs.m_ptStart;
			this.m_ptEnd = rhs.m_ptEnd;
			this.m_dBulge = rhs.m_dBulge;
			this.m_dStartElevation = rhs.m_dStartElevation;
			this.m_dEndElevation = rhs.m_dEndElevation;
			this.m_dLeftWidth = rhs.m_dLeftWidth;
			this.m_dRightWidth = rhs.m_dRightWidth;
			this.m_dVertArcRadius = rhs.m_dVertArcRadius;
		}

		public SegmentData(XYZ ptStart, XYZ ptEend, double dBulge, double dStartElevation, double dEndElevation, double dLeftWidth, double dRightWidth, double dVertArcRadius)
		{
			this.m_ptStart = ptStart;
			this.m_ptEnd = ptEend;
			this.m_dBulge = dBulge;
			this.m_dStartElevation = dStartElevation;
			this.m_dEndElevation = dEndElevation;
			this.m_dLeftWidth = dLeftWidth;
			this.m_dRightWidth = dRightWidth;
			this.m_dVertArcRadius = dVertArcRadius;
		}

		public bool Center(ref XYZ ptCenter)
		{
			if (Geometry.IsEqual(this.Bulge, 0.0))
			{
				return false;
			}
			Geometry.GetCenterWithBulge(this.StartPoint, this.EndPoint, this.Bulge, ref ptCenter);
			return true;
		}

		public bool Radius(ref double dRadius)
		{
			if (Geometry.IsEqual(this.Bulge, 0.0))
			{
				return false;
			}
			Geometry.GetRadiusWithBulge(this.StartPoint, this.EndPoint, this.Bulge, ref dRadius);
			return true;
		}

		public double Length()
		{
			if (Geometry.IsEqual(this.Bulge, 0.0))
			{
				return this.m_ptStart.DistanceTo(this.m_ptEnd);
			}
			XYZ xyz = null;
			double num = 0.0;
			double dSAngle = 0.0;
			double dEAngle = 0.0;
			Geometry.GetArcInfoWithBulge(this.m_ptStart, this.m_ptEnd, this.m_dBulge, ref xyz, ref num, ref dSAngle, ref dEAngle);
			double num2 = Geometry.BetweenTheAngles(dSAngle, dEAngle, true);
			return num * num2;
		}

		public Curve GetCurve(Application app)
		{
			if (Geometry.IsEqual(this.Bulge, 0.0))
			{
				return YJKLineEx.YJKGetBound(this.m_ptStart, this.m_ptEnd);
			}
			XYZ ptCenter = null;
			this.Center(ref ptCenter);
			XYZ normal = XYZ.BasisZ;
			if (Geometry.LessThan(this.m_dBulge, 0.0))
			{
				normal = -XYZ.BasisZ;
			}
			XYZ radianPnt = Geometry.CalculatMidPoint(this.m_ptStart, this.m_ptEnd, ptCenter, normal);
			return app.CreatYJKArc(this.m_ptStart, this.m_ptEnd, radianPnt);
		}

		public bool GetPointAtDist(double dist, ref XYZ pt)
		{
			double val = this.Length();
			if (Geometry.Lessthan_Or_Equal(val, dist))
			{
				return false;
			}
			XYZ xyz = null;
			if (this.Center(ref xyz))
			{
				double num = xyz.DistanceTo(this.StartPoint);
				double num2 = dist / num;
				if (Geometry.LessThan(this.m_dBulge, 0.0))
				{
					pt = xyz + Geometry.RotateTo(this.StartPoint - xyz, -num2, XYZ.BasisZ);
				}
				else
				{
					pt = xyz + Geometry.RotateTo(this.StartPoint - xyz, num2, XYZ.BasisZ);
				}
			}
			else
			{
				pt = this.StartPoint + (this.EndPoint - this.StartPoint).Normalize() * dist;
			}
			return true;
		}

		public XYZ MidPoint()
		{
			XYZ result;
			if (Geometry.IsEqual(this.Bulge, 0.0))
			{
				result = Geometry.CalculatMidPoint(this.m_ptStart, this.m_ptEnd);
			}
			else
			{
				XYZ ptCenter = null;
				this.Center(ref ptCenter);
				XYZ normal = XYZ.BasisZ;
				if (Geometry.LessThan(this.m_dBulge, 0.0))
				{
					normal = -XYZ.BasisZ;
				}
				result = Geometry.CalculatMidPoint(this.m_ptStart, this.m_ptEnd, ptCenter, normal);
			}
			return result;
		}

		public void Reverse()
		{
			XYZ ptStart = this.m_ptStart;
			this.m_ptStart = this.m_ptEnd;
			this.m_ptEnd = ptStart;
			this.m_dBulge = -this.m_dBulge;
			double dStartElevation = this.m_dStartElevation;
			this.m_dStartElevation = this.m_dEndElevation;
			this.m_dEndElevation = dStartElevation;
			double dLeftWidth = this.m_dLeftWidth;
			this.m_dLeftWidth = this.m_dRightWidth;
			this.m_dRightWidth = dLeftWidth;
		}

		public static bool CanBeMerged(SegmentData segmentData1, SegmentData segmentData2)
		{
			XYZ xyz = null;
			XYZ xyz2 = null;
			bool flag = segmentData1.Center(ref xyz);
			bool flag2 = segmentData2.Center(ref xyz2);
			if (flag != flag2)
			{
				return false;
			}
			if (!Geometry.IsEqual(segmentData1.LeftWidth, segmentData2.LeftWidth) || !Geometry.IsEqual(segmentData1.RightWidth, segmentData2.RightWidth))
			{
				return false;
			}
			if (flag)
			{
				if (!xyz.IsAlmostEqualTo(xyz2))
				{
					return false;
				}
				double val = 0.0;
				double val2 = 0.0;
				segmentData1.Radius(ref val);
				segmentData2.Radius(ref val2);
				if (!Geometry.IsEqual(val, val2))
				{
					return false;
				}
			}
			else
			{
				XYZ xyz3 = new XYZ(segmentData1.StartPoint.X, segmentData1.StartPoint.Y, 0.0);
				XYZ xyz4 = new XYZ(segmentData1.EndPoint.X, segmentData1.EndPoint.Y, 0.0);
				XYZ xyz5 = (xyz4 - xyz3).Normalize();
				XYZ xyz6 = new XYZ(segmentData2.StartPoint.X, segmentData2.StartPoint.Y, 0.0);
				XYZ xyz7 = new XYZ(segmentData2.EndPoint.X, segmentData2.EndPoint.Y, 0.0);
				XYZ xyz8 = (xyz7 - xyz6).Normalize();
				if (!xyz5.IsAlmostEqualTo(xyz8))
				{
					return false;
				}
			}
			double val3 = (segmentData1.EndElevation - segmentData1.StartElevation) / (segmentData2.EndElevation - segmentData2.StartElevation);
			double val4 = segmentData1.Length() / segmentData2.Length();
			return Geometry.IsEqual(val3, val4, 0.1) && (segmentData1.StartPoint.IsAlmostEqualTo(segmentData2.EndPoint) || segmentData1.EndPoint.IsAlmostEqualTo(segmentData2.StartPoint));
		}

		public static bool MergeSegmentData(SegmentData segmentData1, SegmentData segmentData2, ref SegmentData mergedSegmentData)
		{
			if (!SegmentData.CanBeMerged(segmentData1, segmentData2))
			{
				return false;
			}
			XYZ centerPt = null;
			XYZ xyz = null;
			bool flag = segmentData1.Center(ref centerPt);
			segmentData2.Center(ref xyz);
			double dBulge = 0.0;
			double leftWidth = segmentData1.LeftWidth;
			double rightWidth = segmentData1.RightWidth;
			double vertArcRadius = segmentData1.VertArcRadius;
			XYZ startPoint;
			XYZ endPoint;
			double startElevation;
			double endElevation;
			if (segmentData1.StartPoint.IsAlmostEqualTo(segmentData2.EndPoint))
			{
				startPoint = segmentData2.StartPoint;
				endPoint = segmentData1.EndPoint;
				startElevation = segmentData2.StartElevation;
				endElevation = segmentData1.EndElevation;
				if (flag)
				{
					dBulge = Geometry.GetBulge(startPoint, endPoint, centerPt, Geometry.GreaterThan(segmentData1.Bulge, 0.0));
				}
			}
			else
			{
				startPoint = segmentData1.StartPoint;
				endPoint = segmentData2.EndPoint;
				startElevation = segmentData1.StartElevation;
				endElevation = segmentData2.EndElevation;
				if (flag)
				{
					dBulge = Geometry.GetBulge(startPoint, endPoint, centerPt, Geometry.GreaterThan(segmentData1.Bulge, 0.0));
				}
			}
			mergedSegmentData = new SegmentData(startPoint, endPoint, dBulge, startElevation, endElevation, leftWidth, rightWidth, vertArcRadius);
			return true;
		}

		public static bool SplitSegmentDataAtDist(SegmentData segmentData, double dist, ref SegmentData halfSegmentData1, ref SegmentData halfSegmentData2)
		{
			double num = segmentData.Length();
			if (Geometry.Lessthan_Or_Equal(num, dist))
			{
				return false;
			}
			XYZ startPoint = segmentData.StartPoint;
			XYZ endPoint = segmentData.EndPoint;
			XYZ xyz = null;
			if (!segmentData.GetPointAtDist(dist, ref xyz))
			{
				return false;
			}
			double startElevation = segmentData.StartElevation;
			double endElevation = segmentData.EndElevation;
			double num2 = startElevation + (endElevation - startElevation) / num * dist;
			double leftWidth = segmentData.LeftWidth;
			double rightWidth = segmentData.RightWidth;
			XYZ centerPt = null;
			if (segmentData.Center(ref centerPt))
			{
				bool isAnticlockwise = Geometry.GreaterThan(segmentData.Bulge, 0.0);
				double bulge = Geometry.GetBulge(startPoint, xyz, centerPt, isAnticlockwise);
				double bulge2 = Geometry.GetBulge(xyz, endPoint, centerPt, isAnticlockwise);
				halfSegmentData1 = new SegmentData(startPoint, xyz, bulge, startElevation, num2, leftWidth, rightWidth, 0.0);
				halfSegmentData2 = new SegmentData(xyz, endPoint, bulge2, num2, endElevation, leftWidth, rightWidth, 0.0);
			}
			else
			{
				halfSegmentData1 = new SegmentData(startPoint, xyz, 0.0, startElevation, num2, leftWidth, rightWidth, 0.0);
				halfSegmentData2 = new SegmentData(xyz, endPoint, 0.0, num2, endElevation, leftWidth, rightWidth, 0.0);
			}
			return true;
		}

		private XYZ m_ptStart;

		private XYZ m_ptEnd;

		private double m_dBulge;

		private double m_dStartElevation;

		private double m_dEndElevation;

		private double m_dLeftWidth;

		private double m_dRightWidth;

		private double m_dVertArcRadius;
	}
}
